#pragma once
#include <spdlog/spdlog.h>
#include <spdlog/async.h>
#include <spdlog/sinks/rotating_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <vector>
#include <iostream>
#include <string>
#include "Singleton.h"
// 必须定义这个宏,才能输出文件名和行号，如果使用了nlohmann，则在CMakeLists里面定义
// 在使用时还需要使用SPDLOG_LOGGER_XXX()才可以正确输出
//  #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE

//定义了几个可以直接使用的宏，若不想使用则要创建对象再使用SPDLOG_LOGGER_XXX()
#define LOG_INFO(msg, ...) SPDLOG_LOGGER_INFO(Logger::GetInstance()->getLogger(), msg, ##__VA_ARGS__)
#define LOG_DEBUG(msg, ...) SPDLOG_LOGGER_DEBUG(Logger::GetInstance()->getLogger(), msg, ##__VA_ARGS__)
#define LOG_ERROR(msg, ...) SPDLOG_LOGGER_ERROR(Logger::GetInstance()->getLogger(), msg, ##__VA_ARGS__)
#define LOG_WARN(msg, ...) SPDLOG_LOGGER_WARN(Logger::GetInstance()->getLogger(), msg, ##__VA_ARGS__)

#define LOG_DB_INFO(msg, ...) SPDLOG_LOGGER_INFO(Logger::GetInstance()->getDBLogger(), msg, ##__VA_ARGS__)
#define LOG_DB_DEBUG(msg, ...) SPDLOG_LOGGER_DEBUG(Logger::GetInstance()->getDBLogger(), msg, ##__VA_ARGS__)
#define LOG_DB_ERROR(msg, ...) SPDLOG_LOGGER_ERROR(Logger::GetInstance()->getDBLogger(), msg, ##__VA_ARGS__)
#define LOG_DB_WARN(msg, ...) SPDLOG_LOGGER_WARN(Logger::GetInstance()->getDBLogger(), msg, ##__VA_ARGS__)

#define LOG_REDIS_INFO(msg, ...) SPDLOG_LOGGER_INFO(Logger::GetInstance()->getREDISLogger(), msg, ##__VA_ARGS__)
#define LOG_REDIS_DEBUG(msg, ...) SPDLOG_LOGGER_DEBUG(Logger::GetInstance()->getREDISLogger(), msg, ##__VA_ARGS__)
#define LOG_REDIS_ERROR(msg, ...) SPDLOG_LOGGER_ERROR(Logger::GetInstance()->getREDISLogger(), msg, ##__VA_ARGS__)
#define LOG_REDIS_WARN(msg, ...) SPDLOG_LOGGER_WARN(Logger::GetInstance()->getREDISLogger(), msg, ##__VA_ARGS__)

class Logger : public Singleton<Logger>
{
    friend class Singleton<Logger>;

public:
    ~Logger()
    {
        std::cout << "Thist is Logger destructor" << std::endl;
        spdlog::drop_all();
        spdlog::shutdown();
    }
    //获取默认Logger
    std::shared_ptr<spdlog::logger> getLogger()
    {
        return _default_logger;
    }
    //获取数据库Logger
    std::shared_ptr<spdlog::logger> getDBLogger()
    {
        return _db_logger;
    }
    //获取redisLogger
    std::shared_ptr<spdlog::logger> getREDISLogger()
    {
        return _redis_logger;
    }

private:
    void Init()
    {
        // 初始化异步日志线程池，队列大小为 8192，1 个后台线程
        // spdlog::init_thread_pool(8192, 1);

        auto _sink_console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        // 格式为[日期时间] [日志级别] [线程名称] [文件名:行号] 内容
        _sink_console->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%t] [%s:%#:%!()] : %v");
        _sink_console->set_level(spdlog::level::trace);
        auto _sink_rotating_file = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
            "../logs/server.log", 1024 * 1024 * 5, 5); // 最大5mb，最多5个文件
        _sink_rotating_file->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] [%s:%#:%!()] : %v");
        _sink_rotating_file->set_level(spdlog::level::trace);

        std::vector<spdlog::sink_ptr> _sinks;
        _sinks.push_back(_sink_rotating_file);
        _sinks.push_back(_sink_console);
        // 创建日志器
        _default_logger = std::make_shared<spdlog::logger>("My_Logger", 
        _sinks.begin(), _sinks.end());
        // _default_logger->flush_on(spdlog::level::trace);

    }
    void db_loggerInit()
    {
        auto _sink_console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        // 格式为[日期时间] [日志级别] [线程名称] [文件名:行号] 内容
        _sink_console->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%t] [%s:%#:%!()] : %v");
        _sink_console->set_level(spdlog::level::trace);
        auto _sink_rotating_file = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
            "../logs/database.log", 1024 * 1024 * 5, 5); // 最大5mb，最多5个文件
        _sink_rotating_file->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] [%s:%#:%!()] : %v");
        _sink_rotating_file->set_level(spdlog::level::trace);

        std::vector<spdlog::sink_ptr> _sinks;
        _sinks.push_back(_sink_rotating_file);
        _sinks.push_back(_sink_console);
        _db_logger = std::make_shared<spdlog::logger>("DB_Logger", 
        _sinks.begin(), _sinks.end());
        // _logger = _db_logger;
        // _db_logger->flush_on(spdlog::level::trace);

    }
    void redis_loggerInit()
    {
        auto _sink_console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        // 格式为[日期时间] [日志级别] [线程名称] [文件名:行号] 内容
        _sink_console->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%n] [%l] [%t] [%s:%#:%!()] : %v");
        _sink_console->set_level(spdlog::level::trace);
        auto _sink_rotating_file = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
            "../logs/redis.log", 1024 * 1024 * 5, 5); // 最大5mb，最多5个文件
        _sink_rotating_file->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] [%s:%#:%!()] : %v");
        _sink_rotating_file->set_level(spdlog::level::trace);

        std::vector<spdlog::sink_ptr> _sinks;
        _sinks.push_back(_sink_rotating_file);
        _sinks.push_back(_sink_console);
        _redis_logger = std::make_shared<spdlog::logger>(
            "REDIS_Logger", 
            _sinks.begin(), _sinks.end());
        // _redis_logger->flush_on(spdlog::level::trace);
    }
    Logger()
    {
        Init();
        db_loggerInit();
        redis_loggerInit();
    }
    // std::shared_ptr<spdlog::sinks::stdout_color_sink_mt> _sink_console;
    // std::shared_ptr<spdlog::sinks::rotating_file_sink_mt> _sink_rotating_file;
    std::shared_ptr<spdlog::logger> _default_logger;
    std::shared_ptr<spdlog::logger> _db_logger;
    std::shared_ptr<spdlog::logger> _redis_logger;
};